package ops

import (
    "context"
    "fcs-api/src/app/business"
    "fcs-api/src/app/handler"
    "fcs-api/src/app/model"
    "os"
    "time"

    "git.inspur.com/x/common/loggerfactory"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/util/wait"
    kube "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/tools/leaderelection"
    "k8s.io/client-go/tools/leaderelection/resourcelock"
)

var logger = loggerfactory.GetLogger()
var ApiHandler handler.APIHandler

// StartWatchTimeoutFunctions 监听状态超时未更新的函数，并进行状态的更新
func StartWatchTimeoutFunctions() {

    config, err := clientcmd.BuildConfigFromFlags("", "")
    if err != nil {
        logger.Error("StartWatchTimeoutFunctions: admin k8s config error: " + err.Error())
        return
    }
    clientSet, err := kube.NewForConfig(config)
    if err != nil {
        logger.Error("StartWatchTimeoutFunctions: get admin k8s clientSet error: " + err.Error())
        return
    }
    id, _ := os.Hostname()
    lock := &resourcelock.LeaseLock{
        LeaseMeta: metav1.ObjectMeta{
            Name:      "fcs",
            Namespace: "fcs",
        },
        Client: clientSet.CoordinationV1(),
        LockConfig: resourcelock.ResourceLockConfig{
            Identity: id,
        },
    }

    ctx := context.Background()

    // start the leader election code loop
    leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
        Lock:            lock,
        ReleaseOnCancel: true,
        LeaseDuration:   60 * time.Second,
        RenewDeadline:   15 * time.Second,
        RetryPeriod:     5 * time.Second,
        Callbacks: leaderelection.LeaderCallbacks{
            // 当取得主权时，持续监听监听超时未更新的函数
            OnStartedLeading: func(ctx context.Context) {
                wait.Until(appendUpdateFunction, time.Duration(model.Base.KsvcWaitingTime)*time.Second, ctx.Done())
            },
            OnStoppedLeading: func() {
                _ = logger.Warn("leader lost: %s", id)
            },
            OnNewLeader: func(identity string) {
                logger.Info("new leader elected: %s", identity)
            },
        },
    })
}

func appendUpdateFunction() {
    infos, err := model.GetTimeoutFuncInfo()
    if err != nil {
        logger.Error("appendUpdateFunction: GetTimeoutFuncInfo error, %s", err)
        return
    }
    fcClient, err := handler.GetFcClient(&ApiHandler)
    if err != nil {
        logger.Error("appendUpdateFunction: GetFcClient error, %s", err)
        return
    }
    for _, info := range infos {
        go func(functionInfo *model.FuncInfo) {
            funcVersion, err := model.GetNewestVersion(functionInfo.Id)
            if err != nil {
                return
            }
            functionInfo.VersionName = funcVersion.VersionName
            business.UpdateFunctionStatus(fcClient, functionInfo)
        }(info)
    }
}
